public class ThreadDemo19 {
    //内部类
    static class WaitTask implements Runnable {
        private Object locker=null;
        public WaitTask(Object locker) {
            this.locker = locker;
        }

        @Override
        public void run() {
            //进行 wait 的线程
            synchronized (locker) {
                System.out.println("wait 开始");
                try {
                    locker.wait();
                    //如果直接调用 wait，相当于是 this.wait，是针对 WaitTask 对象进行等待的
                    //在后面进行通知的 NotifyTask中，要求通知和等待同一个对象
                    //在 NotifyTask中并不容易直接拿到 WaitTask的实例
                    //所以我们创建 locker对象
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("wait 结束");
            }
        }


    }
    static class NotifyTask implements Runnable {
        private Object locker=null;

        public NotifyTask(Object locker) {
            this.locker = locker;
        }

        @Override
        public void run() {
            //进行 notify 的线程
            synchronized (locker) {
                System.out.println("notify 开始");
                //locker.notify();//通知唤醒 当前对象上等待的线程
                locker.notifyAll();

                System.out.println("notify 结束");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //专门创建一个对象，负责进行 加锁/通知 的操作
        Object locker=new Object();

        Thread t1=new Thread(new WaitTask(locker));
        Thread t11=new Thread(new WaitTask(locker));
        Thread t12=new Thread(new WaitTask(locker));

        Thread t2=new Thread(new NotifyTask(locker));
        //这样以来，加锁/通知 的操作都是对同一个对象 locker

        t1.start();
        t11.start();
        t12.start();

        Thread.sleep(3000);
        System.out.println("=======");

        t2.start();

    }


}
